7.05. Справочник по SOAP
Справочник по SOAP
1. Общая структура SOAP-сообщения
SOAP-сообщение — это XML-документ с фиксированной структурой, определяемой схемами http://schemas.xmlsoap.org/soap/envelope/ (SOAP 1.1) или http://www.w3.org/2003/05/soap-envelope (SOAP 1.2).
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header> <!-- Необязательный -->
<!-- Заголовки SOAP -->
</soap:Header>
<soap:Body> <!-- Обязательный -->
<!-- Тело сообщения: вызов операции, ответ или Fault -->
</soap:Body>
</soap:Envelope>
⚠ Валидация: Всё содержимое
<soap:Body>и<soap:Header>должно быть в пространствах имён, отличных отhttp://schemas.xmlsoap.org/soap/envelope/, иначе нарушается спецификация (см. Section 4, SOAP 1.1; Section 2.6, SOAP 1.2).
2. Элемент <soap:Envelope>
Атрибуты:
| Атрибут | Обязательность | Значение по умолчанию | Описание |
|---|---|---|---|
encodingStyle | ❌ (устаревший) | — | Указывает правила сериализации данных (например, http://schemas.xmlsoap.org/soap/encoding/). Устарел в SOAP 1.2. Не рекомендуется: большинство реализаций используют XML Schema (XSD)-описания типов, а не soap:encoding. |
mustUnderstand | ❌ (нельзя) | — | Запрещён на <Envelope>. Разрешён только на элементах внутри <Header>. |
role / actor | ❌ (нельзя) | — | Атрибут actor (SOAP 1.1) / role (SOAP 1.2) недопустим на <Envelope>. |
🔹
encodingStyleв SOAP 1.2 — не определён (введён в SOAP 1.1, но признан избыточным; в 1.2 удалён, хотя в схеме может присутствовать как расширяемый атрибут*).
3. Элемент <soap:Header>
Опциональный. Содержит заголовки — метаданные, модифицирующие поведение обработки сообщения (аутентификация, маршрутизация, транзакции и т.п.).
Структура подзаголовка:
<ns:Security xmlns:ns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
soap:mustUnderstand="1"
soap:role="http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver">
<!-- Содержимое заголовка -->
</ns:Security>
Атрибуты подзаголовка (на каждом дочернем элементе <Header>):
| Атрибут | Применимость | Возможные значения | Описание |
|---|---|---|---|
soap:mustUnderstand | ✅ Обязателен при необходимости | "0" | "1" | "false" | "true" | Указывает, должен ли получатель (с заданной role) понимать и обработать заголовок. При 1/true и невозможности обработки — возвращается soap:MustUnderstand Fault. |
soap:actor | ✅ Только SOAP 1.1 | URI | Определяет, кому адресован заголовок среди цепочки получателей (intermediaries). Устаревшее в SOAP 1.2. |
soap:role | ✅ Только SOAP 1.2 | Один из URI: • http://www.w3.org/2003/05/soap-envelope/role/none • http://www.w3.org/2003/05/soap-envelope/role/ultimateReceiver • http://www.w3.org/2003/05/soap-envelope/role/next • произвольный URI (для intermediaries) | Замена actor. Определяет роль получателя. Все заголовки без role по умолчанию → ultimateReceiver. |
soap:relay | ✅ Только SOAP 1.2 | "0" | "1" | "false" | "true" | Если 1, промежуточный узел, не распознающий заголовок, должен передать его дальше. Игнорируется при mustUnderstand="1". По умолчанию — 0. |
⚠ Проверка обработки:
- Получатель с определённой
roleобязан обработать все заголовки, адресованные ему (roleсовпадает или отсутствует и роль —ultimateReceiver).- При
mustUnderstand="1"и отсутствии обработчика — ошибка, даже еслиrelay="1".
4. Элемент <soap:Body>
Обязателен. Содержит тело запроса/ответа либо soap:Fault.
Возможные дочерние элементы:
| Тип | Описание |
|---|---|
| RPC-стиль (устаревший) | <methodName> с параметрами как дочерними элементами. Требует encodingStyle. Не рекомендуется. |
| Document/Literal (современный) | Элемент с именем операции (например, <GetUserRequest>) или <xsd:element> из WSDL. Содержимое строго типизировано XSD-схемой. |
<soap:Fault> | Стандартный элемент ошибки. Единственный допустимый дочерний элемент в случае ответа с ошибкой. |
🔹 В одном
<Body>допускается только один корневой элемент (кромеFault— он единственный).
5. Элемент <soap:Fault> (ошибки)
Стандартный механизм сообщений об ошибках. Обязательный в SOAP 1.1 и 1.2. Размещается только внутри <Body>, единственный дочерний элемент.
Структура SOAP 1.1:
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring xml:lang="en">Invalid request</faultstring>
<faultactor>http://example.com/intermediary</faultactor> <!-- ❌ в SOAP 1.2 -->
<detail>
<ns:ValidationError xmlns:ns="...">
<code>USR_001</code>
<message>UserID is required</message>
</ns:ValidationError>
</detail>
</soap:Fault>
Структура SOAP 1.2:
<soap:Fault xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Code>
<soap:Value>soap:Sender</soap:Value>
<soap:Subcode>
<soap:Value>ns:InvalidFormat</soap:Value>
</soap:Subcode>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">Invalid XML format</soap:Text>
<soap:Text xml:lang="ru">Неверный формат XML</soap:Text>
</soap:Reason>
<soap:Node>http://example.com/node2</soap:Node> <!-- ✅ аналог faultactor -->
<soap:Role>http://www.w3.org/2003/05/soap-envelope/role/next</soap:Role>
<soap:Detail>
<ns:AppError xmlns:ns="...">
<code>XSD-101</code>
</ns:AppError>
</soap:Detail>
</soap:Fault>
🔹 Поля faultcode (SOAP 1.1) и <Code> (SOAP 1.2)
| Код (SOAP 1.1) | Значение (SOAP 1.2) | Кем генерируется | Описание |
|---|---|---|---|
soap:VersionMismatch | soap:VersionMismatch | Любой | Несовместимая версия SOAP (например, 1.2-сообщение пришлось в 1.1-endpoint). |
soap:MustUnderstand | soap:MustUnderstand | Получатель | Заголовок с mustUnderstand="1" не распознан. |
soap:Client | soap:Sender | Сервер | Ошибка в запросе клиента (некорректные данные, отсутствует обязательный параметр). |
soap:Server | soap:Receiver | Сервер | Ошибка на стороне сервера (исключение, БД недоступна и т.п.). |
🔸 В SOAP 1.2 введены вложенные Subcode, что позволяет детализировать причину:
soap:Sender+ns:AuthenticationFailedsoap:Receiver+ns:DatabaseTimeout
🔹 <detail> / <Detail>
- Обязателен только при
faultcode = Client/Server(SOAP 1.1) илиCode ∈ {Sender, Receiver}(SOAP 1.2). - Должен содержать прикладные данные (не
soap:*). - Не должен включать данные, нарушающие безопасность.
6. Привязка к HTTP — как SOAP передаётся по сети
SOAP не определяет транспорт, но HTTP — самая распространённая привязка (binding). Спецификации:
- SOAP 1.1 → Simple Object Access Protocol (SOAP) 1.1, Section 6
- SOAP 1.2 → SOAP Version 1.2 Part 2: Adjuncts, Section 7
🔹 HTTP-заголовки (обязательные и рекомендуемые)
| Заголовок | Обязательность | Пример значения | Примечания |
|---|---|---|---|
Content-Type | ✅ Обязателен | text/xml; charset=utf-8 (SOAP 1.1) application/soap+xml; charset=utf-8 (SOAP 1.2) | Для SOAP 1.2 charset опционален, но рекомендован. При наличии вложений (MTOM) — multipart/related. |
SOAPAction | ⚠ Только в SOAP 1.1 ❌ Удалён в SOAP 1.2 | "http://example.com/GetUser" | Указывает намерение запроса. Мог быть пустым (""), но не должен отсутствовать. В SOAP 1.2 роль SOAPAction заменяет заголовок Content-Type + элемент <wsa:Action> (WS-Addressing). |
Content-Length | ✅ Обязателен (если не chunked) | 1842 | Стандартный HTTP-заголовок, но критичен для парсинга. |
Host | ✅ Обязателен (HTTP/1.1+) | api.example.com | Стандартный заголовок, но участвует в маршрутизации. |
⚠ Различие SOAP 1.1 / 1.2 в HTTP:
- В SOAP 1.2
SOAPActionзаменён на параметрactionвContent-Type, например:
application/soap+xml; charset=utf-8; action="http://example.com/GetUser"
Однако на практике многие серверы (в т.ч. .NET ASMX, Java Metro) игнорируют этот параметр и полагаются на корневой элемент в<Body>илиwsa:Action.
🔹 HTTP-статусы и их интерпретация
| Статус | Ожидаемое содержимое тела | Комментарий |
|---|---|---|
200 OK | Корректный SOAP-ответ (<Body> с результатом или <Fault>) | Нормальный сценарий. |
500 Internal Server Error | <soap:Fault> (рекомендуется) или HTML | Часто возвращается при необработанном исключении. |
400 Bad Request | <soap:Fault> с soap:Client / soap:Sender | Некорректный XML, нарушение XSD-схемы и т.д. |
415 Unsupported Media Type | — | Если Content-Type не text/xml (1.1) / application/soap+xml (1.2). |
501 Not Implemented | <soap:Fault> с soap:VersionMismatch | Если сервер не поддерживает версию SOAP (например, пришёл 1.2-запрос в 1.1-эндпоинт). |
🔹 Важно: Тело ответа всегда должно быть валидным SOAP-документом (даже при 5xx), иначе клиент не сможет корректно обработать ошибку.
7. Вложения и двоичные данные (Binary Attachments)
SOAP — текстовый XML-протокол. Передача бинарных данных (изображения, PDF, файлы) требует кодирования или упаковки.
Способы:
| Способ | Стандарт | Описание |
|---|---|---|
| Base64-вложение в XML | Нестандартный, но распространённый | <data>YWJj...</data> — просто, но +33% объём, высокий overhead парсинга. Подходит для небольших данных (<100 КБ). |
| SwA (SOAP with Attachments) | Устаревший (RFC 2387 + SOAP 1.1 Note) | multipart/related: SOAP-сообщение + MIME-вложения. Не поддерживается WSDL 2.0, несовместим с MTOM. |
| MTOM (Message Transmission Optimization Mechanism) | ✅ W3C Recommendation (2005) | Оптимизирует xsd:base64Binary/xsd:hexBinary в XOP (XML-binary Optimized Packaging). Использует multipart/related, но совместим с WSDL и XSD. |
| XOP (XML-binary Optimized Packaging) | ✅ W3C (часть MTOM) | Стандартная замена base64 на <xop:Include href="cid:..."/>. MTOM — это XOP + HTTP-привязка. |
🔹 Пример MTOM/XOP (в SOAP 1.2)
HTTP-заголовки:
Content-Type: multipart/related;
type="application/xop+xml";
start="<root.message@cxf.apache.org>";
start-info="application/soap+xml; charset=utf-8";
boundary="uuid:12345678-90ab-cdef-1234-567890abcdef"
Тело сообщения:
--uuid:12345678-90ab-cdef-1234-567890abcdef
Content-Type: application/xop+xml; charset=utf-8; type="application/soap+xml"
Content-Transfer-Encoding: binary
Content-ID: <root.message@cxf.apache.org>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<ns1:UploadDocument xmlns:ns1="http://example.com/">
<document>
<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include"
href="cid:document.pdf@example.com"/>
</document>
</ns1:UploadDocument>
</soap:Body>
</soap:Envelope>
--uuid:12345678-90ab-cdef-1234-567890abcdef
Content-Type: application/pdf
Content-Transfer-Encoding: binary
Content-ID: <document.pdf@example.com>
%PDF-1.4...
--uuid:12345678-90ab-cdef-1234-567890abcdef--
🔸 Поддержка:
- .NET:
basicHttpBinding/wsHttpBindingсmessageEncoding="Mtom"- Java (JAX-WS): аннотация
@MTOMили настройкаBindingProvider- Apache CXF:
<jaxws:binding>с<xjc:extension>иmtom-enabled="true"
8. WSDL и SOAP: как описывается интерфейс
WSDL (Web Services Description Language) — XML-документ, описывающий контракт веб-сервиса, включая SOAP-привязки.
Структура WSDL 1.1 (кратко):
<definitions targetNamespace="http://example.com/">
<types> <!-- XSD-схемы типов -->
<xsd:schema>...</xsd:schema>
</types>
<message name="GetUserRequest">
<part name="parameters" element="tns:GetUser"/>
</message>
<portType name="UserServicePortType">
<operation name="GetUser">
<input message="tns:GetUserRequest"/>
<output message="tns:GetUserResponse"/>
</operation>
</portType>
<binding name="UserServiceBinding" type="tns:UserServicePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetUser">
<soap:operation soapAction="http://example.com/GetUser"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="UserService">
<port name="UserServicePort" binding="tns:UserServiceBinding">
<soap:address location="https://api.example.com/user"/>
</port>
</service>
</definitions>
🔹 Ключевые атрибуты в <soap:binding> и <soap:operation>
| Элемент | Атрибут | Возможные значения | Примечание |
|---|---|---|---|
<soap:binding> | style | rpc | document | document — современный стандарт (сообщение = XSD-элемент). rpc — устаревший (сообщение = вызов метода). |
<soap:binding> | transport | http://schemas.xmlsoap.org/soap/http | http://www.w3.org/2003/05/soap/bindings/HTTP/ | Первое — SOAP 1.1, второе — SOAP 1.2. |
<soap:operation> | soapAction | URI | Требуется в WSDL 1.1 для SOAP 1.1. В WSDL 2.0 заменён на wsdlx:safe и http:operation. |
<soap:body> | use | literal | encoded | literal — данные соответствуют XSD. encoded — использует soap:encodingStyle (устарело, несовместимо с WS-I BP). |
<soap:body> | parts | список имён <part> | Опционален, если один параметр. |
🔹 WS-I Basic Profile 1.1 запрещает:
use="encoded"style="rpc"soap:encodingStyle→ Рекомендуется толькоdocument/literal.
9. Безопасность: WS-Security (WSS)
SOAP не содержит встроенной безопасности. WS-Security (OASIS Standard) — основной механизм защиты сообщений.
Элементы в <soap:Header>:
| Элемент | Пространство имён | Назначение |
|---|---|---|
<wsse:Security> | http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd | Контейнер для всех элементов безопасности. |
<wsse:UsernameToken> | то же | Аутентификация по логину/паролю. |
<wsse:BinarySecurityToken> | то же | Сертификат (X.509), SAML-утверждение, Kerberos-тикет. |
<ds:Signature> | http://www.w3.org/2000/09/xmldsig# | Цифровая подпись (чаще всего enveloped). |
<xenc:EncryptedData> | http://www.w3.org/2001/04/xmlenc# | Шифрование элемента (чаще <Body> или <UsernameToken>). |
<wsu:Timestamp> | http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd | Защита от replay-атак. |
🔹 Пример <wsse:UsernameToken> (plain text — не для production):
<wsse:Security soap:mustUnderstand="1"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>admin</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
secret
</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
🔹 Рекомендуемые Type для <wsse:Password>:
| Type URI | Описание |
|---|---|
#PasswordText | Открытый текст (только с TLS). |
#PasswordDigest | Base64(SHA-1(nonce + created + password)). Требует <wsse:Nonce> и <wsu:Created>. |
#PasswordDigest + Nonce + Created — стандартный способ без TLS на уровне канала. |
🔹 <wsu:Timestamp> (обязателен при PasswordDigest и для защиты от replay):
<wsu:Timestamp wsu:Id="TS-1"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Created>2025-11-21T10:00:00Z</wsu:Created>
<wsu:Expires>2025-11-21T10:05:00Z</wsu:Expires>
</wsu:Timestamp>
🔸 Поддержка:
- .NET: WSE 3.0 (устарело),
CustomBindingсSecurityBindingElement, илиwsHttpBinding+MessageCredentialType.UserName.- Java: Apache WSS4J (в CXF), Metro
@Policy.
10. WS-Addressing (W3C Recommendation, 2006)
SOAP изначально не определял адресацию сообщений — откуда, куда, куда отвечать, куда отправлять ошибки.
WS-Addressing (WSA) решает эти задачи независимо от транспорта (HTTP, JMS, SMTP), обеспечивая маршрутизацию, корреляцию и асинхронность.
Основные элементы в <soap:Header>:
| Элемент | Обязательность | Пример значения | Описание |
|---|---|---|---|
<wsa:To> | ❌ | https://api.example.com/UserService | Конечная точка, которой адресовано сообщение. Аналог HTTP URL, но в сообщении. |
<wsa:Action> | ✅ (в wsaw:UsingAddressing) | http://example.com/UserService/GetUserRequest | Указывает намерение (semantic), заменяет SOAPAction. Используется для диспетчеризации операций. |
<wsa:MessageID> | ❌ | urn:uuid:123e4567-e89b-12d3-a456-426614174000 | Уникальный идентификатор сообщения (для логирования, дедупликации). |
<wsa:ReplyTo> | ❌ | <wsa:Address>http://client.example.com/callback</wsa:Address> | Куда отправить ответ (асинхронный вызов). Если отсутствует — синхронный (ответ в HTTP response). |
<wsa:FaultTo> | ❌ | аналогично ReplyTo | Куда отправить Fault, если отличается от ReplyTo. |
<wsa:From> | ❌ | аналогично | Кто отправитель (для аудита, маршрутизации). |
<wsa:RelatesTo> | ❌ | <wsa:RelatesTo RelationshipType="http://www.w3.org/2005/08/addressing/reply">urn:uuid:... | Корреляция: ответ → запрос, ошибка → запрос и т.д. |
Пространства имён:
- Основное:
http://www.w3.org/2005/08/addressing(рекомендуемое) - Устаревшее:
http://schemas.xmlsoap.org/ws/2004/08/addressing
🔹 Специальные URI-значения:
| URI | Назначение |
|---|---|
http://www.w3.org/2005/08/addressing/anonymous | Ответ в том же HTTP-соединении (синхронно). Значение по умолчанию для ReplyTo, если не указан. |
http://www.w3.org/2005/08/addressing/none | Не отправлять ответ (fire-and-forget). |
http://www.w3.org/2005/08/addressing/fault | Отправлять Fault в FaultTo, даже если ReplyTo указан. |
🔹 Пример асинхронного вызова:
<soap:Header>
<wsa:MessageID>urn:uuid:1111</wsa:MessageID>
<wsa:Action>http://example.com/LongOperation</wsa:Action>
<wsa:ReplyTo>
<wsa:Address>https://client.example.com/async-response</wsa:Address>
</wsa:ReplyTo>
<wsa:FaultTo>
<wsa:Address>https://client.example.com/async-fault</wsa:Address>
</wsa:FaultTo>
</soap:Header>
<soap:Body>
<ns:LongOperationRequest>...</ns:LongOperationRequest>
</soap:Body>
🔸 Поддержка:
- .NET:
CustomBindingсTextMessageEncodingBindingElement+HttpTransportBindingElement, иChannelFactory<IDuplexChannel>; илиwsHttpBindingсuseDefaultWebProxy="false"иlistenUri.- Java (CXF):
<jaxws:server>+<jaxws:properties>→org.apache.cxf.ws.addressing.MAPAggregator=true.
11. WS-ReliableMessaging (WS-RM, OASIS Standard)
Обеспечивает гарантированную, упорядоченную, без дубликатов доставку SOAP-сообщений поверх ненадёжных транспортов.
Основные концепции:
- RM Source — отправитель
- RM Destination — получатель
- Sequence — упорядоченная серия сообщений (идентифицируется
Identifier) - Acknowledgement — подтверждение получения (
<wsrm:SequenceAcknowledgement>)
Элементы в <soap:Header>:
| Элемент | Описание |
|---|---|
<wsrm:Sequence> | В запросе: Identifier + MessageNumber (1,2,3…). В ответе — может отсутствовать. |
<wsrm:SequenceAcknowledgement> | Список полученных MessageNumber; может быть битовой картой или диапазонами. |
<wsrm:CreateSequence> | Инициализация новой последовательности (в отдельном handshake-обмене). |
<wsrm:CloseSequence> | Завершение последовательности. |
Пример <wsrm:Sequence>:
<wsrm:Sequence xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm">
<wsrm:Identifier>urn:uuid:abcd-1234</wsrm:Identifier>
<wsrm:MessageNumber>3</wsrm:MessageNumber>
</wsrm:Sequence>
🔹 Поведение:
- При потере сообщения —
RM Destinationне подтверждает его номер →RM Sourceповторяет. - При дубликате —
MessageNumberуже учтён → игнорируется. - При нарушении порядка — сообщения буферизуются до прихода предыдущих.
🔸 Поддержка:
- .NET:
NetTcpBindingсreliableSession.Enabled = true;wsHttpBinding— только если кастомизировано (не из коробки).- Java: Apache Sandesha2 (в CXF), Metro WS-RM.
⚠ Ограничения: WS-RM работает только на уровне сообщений, не обеспечивает транзакционной целостности. Для этого — см. WS-AtomicTransaction.
12. WS-Coordination и WS-AtomicTransaction
Для участия SOAP-сервисов в распределённых транзакциях (2PC — two-phase commit).
Архитектура:
- Инициатор создаёт координационный контекст через Activation Service (
wscoor:CreateCoordinationContext). - Сервисы регистрируются в контексте через Registration Service (
wscoor:Register). - Координатор управляет фазами
Prepare→Commit/Rollback.
Пространства имён:
- Coordination:
http://schemas.xmlsoap.org/ws/2004/10/wscoor - AtomicTransaction:
http://schemas.xmlsoap.org/ws/2004/10/wsat
Элемент в <soap:Header>:
<wscoor:CoordinationContext>
<wscoor:Identifier>urn:uuid:tx-789</wscoor:Identifier>
<wscoor:CoordinationType>
http://schemas.xmlsoap.org/ws/2004/10/wsat
</wscoor:CoordinationType>
<wscoor:RegistrationService>
<wsa:Address>https://coordinator.example.com/register</wsa:Address>
</wscoor:RegistrationService>
</wscoor:CoordinationContext>
Операции в теле:
<wsat:Prepare>→ сервис отвечает<wsat:Prepared>/<wsat:Aborted><wsat:Commit>/<wsat:Rollback>
🔸 Поддержка:
- .NET:
System.Transactions+TransactionScope+WS-AtomicTransactionbinding (только в enterprise-средах, напр. с MSDTC).- Java: Narayana (JBoss), Atomikos — через JTA + кастомные SOAP-перехватчики.
⚠ Практическое замечание: WS-AT редко используется в публичных API из-за сложности, latency и statefulness. Чаще применяют компенсирующие транзакции (Saga) или отказываются от распределённой транзакционности.
13. Профили совместимости и ограничения
🔹 WS-I Basic Profile 1.1 (и 2.0) — де-факто стандарт для совместимости
| Требование | Значение |
|---|---|
| Стиль сообщения | document/literal |
| Кодировка | use="literal" (запрещено encoded) |
soap:encodingStyle | ❌ запрещён |
SOAPAction | Должен быть указан (может быть "") |
| WSDL | Должен быть валиден, один portType на binding, один port на service |
| Fault | <faultcode> из стандартного набора, <detail> — только при Client/Server |
🔹 WS-I Attachments Profile 1.0
- Запрещает SwA
- Рекомендует MTOM/XOP для бинарных данных
- Требует указания
Content-IDвxop:Include/@href
🔹 WS-I Security Profile 1.1
- Разрешает только
#PasswordTextс TLS или#PasswordDigestсNonce/Created - Требует
wsu:TimestampприPasswordDigest - Запрещает подпись/шифрование без политики (
wsse:Securityбезwsu:Id— недопустимо)
14. Отладка и инструменты
| Инструмент | Возможности |
|---|---|
| SoapUI (ReadyAPI) | Генерация из WSDL, mocking, load testing, security testing (WS-Security), MTOM, WS-A, WS-RM. |
| Fiddler / Charles | Перехват HTTP(S), просмотр/редактирование raw SOAP, breakpoint-отладка. |
| Wireshark | Анализ на уровне TCP/HTTP, фильтрация по xml, soap, wsa. |
| Postman | Поддержка SOAP (начиная с v8.0): импорт WSDL, raw XML, переменные, pre-request scripts для wsse:UsernameToken. |
| svcutil.exe (.NET) | Генерация клиентского кода из WSDL: svcutil /t:metadata /serviceContract. |
| wsimport (JAX-WS) | wsimport -keep -s src/ http://example.com/service?wsdl → генерация Java-классов. |
🔹 Пример: подпись wsse:UsernameToken с PasswordDigest в Postman (Pre-request Script):
const crypto = require('crypto-js');
const nonce = CryptoJS.lib.WordArray.random(16).toString(CryptoJS.enc.Base64);
const created = new Date().toISOString();
const password = pm.environment.get("password");
const digest = CryptoJS.SHA1(
CryptoJS.enc.Base64.parse(nonce) +
CryptoJS.enc.Utf8.parse(created) +
CryptoJS.enc.Utf8.parse(password)
).toString(CryptoJS.enc.Base64);
pm.request.headers.add({
key: 'Content-Type',
value: 'text/xml;charset=UTF-8'
});
// Вставить в XML-тело:
// <wsse:Nonce EncodingType="...#Base64Binary">{{nonce}}</wsse:Nonce>
// <wsu:Created>{{created}}</wsu:Created>
// <wsse:Password Type="...#PasswordDigest">{{digest}}</wsse:Password>
15. Сравнение SOAP 1.1 и SOAP 1.2: таблица различий
| Категория | SOAP 1.1 | SOAP 1.2 | Комментарий |
|---|---|---|---|
| Пространство имён Envelope | http://schemas.xmlsoap.org/soap/envelope/ | http://www.w3.org/2003/05/soap-envelope | Критично для валидации. |
| Fault-структура | Плоская: <faultcode>, <faultstring>, <faultactor>, <detail> | Иерархическая: <Code> (с Value/Subcode), <Reason> (множество <Text>), <Node>, <Role>, <Detail> | SOAP 1.2 позволяет локализацию и детализацию ошибок. |
| HTTP Content-Type | text/xml (рекомендовано) | application/soap+xml | В 1.2 charset указывается в параметре charset=utf-8, не в заголовке Content-Type. |
| SOAPAction | Обязательный HTTP-заголовок | Удалён из спецификации; заменён на параметр action в Content-Type или wsa:Action | На практике многие 1.2-серверы игнорируют action в Content-Type. |
encodingStyle | Разрешён (но не рекомендован) | Удалён из схемы (атрибут * допускает его, но не интерпретируется) | Использование encodingStyle нарушает WS-I BP. |
| Обработка неизвестных заголовков | Не регламентировано | Введён атрибут soap:relay: если 1, промежуточный узел передаёт заголовок дальше, даже если не понимает его | Повышает расширяемость. |
Явный role (вместо actor) | actor (URI) | role (ограниченные URI: none, ultimateReceiver, next) | Более строгая семантика маршрутизации. |
| Поддержка Unicode | Неявная | Явно указано, что XML-декларация encoding="UTF-8" предпочтительна | UTF-8 — обязательный минимум реализации. |
| Ошибки верификации XML | Не специфицировано | Введён код soap:DataEncodingUnknown (в Subcode) | Для случаев, когда кодировка не поддерживается. |
🔹 Совместимость:
- Сервер SOAP 1.2 не обязан принимать SOAP 1.1-сообщения.
- Реализации (например, Apache CXF, .NET CoreWCF) часто поддерживают обе версии на одном endpoint’е, но это — расширение, а не стандарт.
16. Поддержка в фреймворках и стеках
🔹 .NET
| Технология | Версия | Поддержка SOAP | Ограничения |
|---|---|---|---|
| ASMX (Web Services) | .NET Framework 1.0–4.8 | SOAP 1.1, document/literal, базовый WS-Security | Устарело, не поддерживает MTOM без костылей, нет WS-A/WS-RM. |
| WCF | .NET Framework 3.0–4.8 | Полная: SOAP 1.1/1.2, MTOM, WS-Security (WSS 1.0/1.1), WS-A, WS-RM, WS-AT | Требует customBinding для тонкой настройки. Не поддерживается в .NET Core 1–2. |
| CoreWCF | .NET 5+ (community) | Порт WCF: basicHttpBinding, wsHttpBinding, MTOM, частично WS-Security | Активно развивается; WS-RM и WS-AT — в roadmap. |
| HttpClient + ручная сериализация | Любая | Полный контроль: можно собрать любой SOAP-пакет | Трудоёмко; рекомендуется только для интеграций с legacy. |
🔹 Java
| Технология | Стек | Поддержка |
|---|---|---|
| JAX-WS (Metro) | Java EE / Jakarta EE | SOAP 1.1/1.2, MTOM, WS-Security (через @Policy), WS-A (частично) |
| Apache CXF | Spring, standalone | Полная: WS-Security (WSS4J), WS-A, WS-RM (Sandesha2), WS-AT (Narayana), MTOM/XOP |
| Spring-WS | Spring Framework | «Contract-first» (только document/literal), MTOM, WS-Security (через WSS4J), но без WSDL generation |
🔹 Python
| Библиотека | Поддержка | Комментарий |
|---|---|---|
| zeep | SOAP 1.1/1.2, WSDL 1.1/2.0, MTOM (частично), WS-Security (UsernameToken, Timestamp, BinarySecurityToken) | Активно поддерживается, типизация через xsd. Лучший выбор. |
| pysimplesoap | SOAP 1.1, базовый WS-Security | Устаревшая, минимальная поддержка. |
| suds-jurko | SOAP 1.1, WSDL, нет MTOM/WS-Security | Не поддерживается с 2014 г. |
🔹 Node.js / JS/TS
| Библиотека | Поддержка |
|---|---|
| node-soap | SOAP 1.1, WSDL, базовый UsernameToken, MTOM (через multipart) |
| strong-soap | Форк node-soap: SOAP 1.2, MTOM, PasswordDigest, WSDL 2.0 |
17. Анти-паттерны и типичные ошибки
| Ошибка | Последствие | Как исправить |
|---|---|---|
<data><![CDATA[...]]></data> внутри xsd:string | Некорректный XML при парсинге: CDATA не сохраняется в объектной модели; нарушает XSD-валидацию (xs:string не допускает CDATA как особую конструкцию). | Использовать <, >, & — XML-парсер сам декодирует. |
xmlns="" внутри <Body> | Элемент попадает в пустое пространство имён, нарушает правило «всё в Body — не в soap-env». Многие фреймворки (CXF, WCF) отклоняют. | Явно указывать xmlns:ns="..." и использовать ns:element. |
в XML-данных | Нестандартная entity — не определена в XML без DTD. Вызовет SAXParseException. | Использовать   (числовой код) или (пробел). |
encodingStyle в SOAP 1.2 | Не интерпретируется; вызывает предупреждения в логах. | Удалить. Типизация — через XSD. |
Отсутствие mustUnderstand="1" у критичных заголовков | Промежуточный узел проигнорирует заголовок → нарушение безопасности/транзакции. | Всегда указывать soap:mustUnderstand="1" для wsse:Security, wsrm:Sequence, wscoor:CoordinationContext. |
<detail> без soap:Client/Server | Нарушение спецификации: <detail> разрешён только при faultcode ∈ {Client, Server}. | Удалять <detail> при VersionMismatch/MustUnderstand. |
18. Когда оставаться на SOAP, а когда мигрировать
| Критерий | Рекомендация | Обоснование |
|---|---|---|
| Требуется ACID-транзакция через сервисы | ✅ SOAP + WS-AT | REST не предоставляет стандартизированного 2PC. |
| Интеграция с гос/банковскими системами (ЕПГУ, Банк России, СМЭВ 3.0) | ✅ SOAP | Требования ГОСТ Р 7.0.97-2016, СМЭВ — строго SOAP/WSDL/WS-Security. |
| Необходима гарантированная доставка (без потерь) | ✅ SOAP + WS-RM | REST требует реализации на уровне приложения (например, idempotency keys + лог). |
| Микросервисы внутри одного домена, agile-разработка | ❌ → REST/GraphQL/gRPC | SOAP замедляет итерации: WSDL, codegen, версионирование контрактов. |
| Высокая нагрузка, low-latency | ❌ → gRPC/protobuf | SOAP/XML — высокий overhead (парсинг, размер). |
| Публичное API для мобильных/веб-клиентов | ❌ → REST/JSON | Поддержка SOAP в браузере — только через прокси; JSON легче для обработки. |
🔹 Эмпирическое правило:
— Если контрагент предоставляет только WSDL → используйте SOAP.
— Если вы владеете обеими сторонами и нет legacy-ограничений → оцените gRPC или REST+OpenAPI.